package com.meituan.catering.management.order.biz.model.converter;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.meituan.catering.management.common.model.biz.UserContextBO;
import com.meituan.catering.management.order.api.http.model.enumeration.CateringOrderItemAccessoryStatusEnum;
import com.meituan.catering.management.order.biz.model.request.PlaceCateringOrderBizRequest;
import com.meituan.catering.management.order.biz.model.request.PrepareCateringOrderBizRequest;
import com.meituan.catering.management.order.biz.model.request.ProduceCateringOrderBizRequest;
import com.meituan.catering.management.order.dao.model.CateringOrderItemAccessoryDO;
import com.meituan.catering.management.order.dao.model.CateringOrderItemDO;
import com.meituan.catering.management.order.remote.model.response.ProductDetailRemoteResponse;
import org.apache.commons.collections4.CollectionUtils;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author Believe
 * Date 2022/5/30 19:27
 */
public class CateringOrderItemAccessoryDOConverter {
    /**
     * 将租户id、订单子项集合、请求、商品信息转换为CateringOrderItemAccessoryDO对象
     *
     * @param tenantId             租户id
     * @param cateringOrderItemDOS 订单子项集合
     * @param itemList             请求item集合
     * @param productMap           RPC商品信息
     * @return
     */
    public static List<CateringOrderItemAccessoryDO> toCateringOrderItemAccessoryDO(Long tenantId,
                                                                                    List<CateringOrderItemDO> cateringOrderItemDOS,
                                                                                    List<PlaceCateringOrderBizRequest.Item> itemList,
                                                                                    Map<Long, ProductDetailRemoteResponse> productMap) {

        List<CateringOrderItemAccessoryDO> cateringOrderItemAccessoryDOList = Lists.newLinkedList();
        for (PlaceCateringOrderBizRequest.Item item : itemList) {
            //根据加料id进行分组
            if (CollectionUtils.isEmpty(item.getAccessories())) {
                return Collections.emptyList();
            }
            Map<Long, CateringOrderItemAccessoryDO> accessoryDOMap = toGroupByAccessoryId(item.getAccessories(), tenantId);
            cateringOrderItemAccessoryDOList = toItemAccessoryDOList(accessoryDOMap, productMap.get(item.getProductId()).getAccessoryGroups());
        }
        //按照序号分组
        Map<String, List<CateringOrderItemAccessoryDO>> accessorySeqMap = toGroupBySeq(cateringOrderItemDOS, cateringOrderItemAccessoryDOList);
        List<CateringOrderItemAccessoryDO> accessoryDOList = toOrderItemId(accessorySeqMap, cateringOrderItemDOS);
        return accessoryDOList;
    }

    /**
     * 给CateringOrderItemAccessoryDO对象设置订单子项id
     *
     * @param accessorySeqMap      按照序号分组的map
     * @param cateringOrderItemDOS CateringOrderItemAccessoryDO集合
     * @return
     */
    private static List<CateringOrderItemAccessoryDO> toOrderItemId(Map<String, List<CateringOrderItemAccessoryDO>> accessorySeqMap,
                                                                    List<CateringOrderItemDO> cateringOrderItemDOS) {
        List<CateringOrderItemAccessoryDO> accessoryDOList = Lists.newLinkedList();
        cateringOrderItemDOS.stream()
                .forEach(cateringOrderItemDO -> accessorySeqMap.get(cateringOrderItemDO.getSeqNo()).stream()
                        .forEach(accessory -> {
                                    accessory.setOrderItemId(cateringOrderItemDO.getId());
                                    accessoryDOList.add(accessory);
                                }
                        ));
        return accessoryDOList;
    }

    /**
     * 对CateringOrderItemAccessoryDO对象进行第一次转换 缺少订单子项id
     *
     * @param accessoryDOMap  根据accessoryId分组的map
     * @param accessoryGroups RPC商品信息 accessory集合
     * @return
     */
    private static List<CateringOrderItemAccessoryDO> toItemAccessoryDOList(Map<Long, CateringOrderItemAccessoryDO> accessoryDOMap,
                                                                            List<ProductDetailRemoteResponse.AccessoryGroup> accessoryGroups) {
        List<CateringOrderItemAccessoryDO> cateringOrderItemAccessoryDOList = Lists.newLinkedList();
        for (ProductDetailRemoteResponse.AccessoryGroup accessoryGroup : accessoryGroups) {
            for (ProductDetailRemoteResponse.AccessoryGroup.Option option : accessoryGroup.getOptions()) {
                if (accessoryDOMap.containsKey(option.getId())) {
                    CateringOrderItemAccessoryDO accessoryDO = accessoryDOMap.get(option.getId());
                    accessoryDO.setProductAccessoryNameOnPlace(option.getName());
                    accessoryDO.setProductAccessoryGroupNameOnPlace(accessoryGroup.getName());
                    accessoryDO.setProductAccessoryUnitPriceOnPlace(new BigDecimal(option.getUnitPrice()));
                    accessoryDO.setProductAccessoryUnitOfMeasureOnPlace(option.getUnitOfMeasure());
                    cateringOrderItemAccessoryDOList.add(accessoryDO);
                }
            }
        }
        return cateringOrderItemAccessoryDOList;
    }

    /**
     * 对第一次分组后的CateringOrderItemAccessoryDO对象集合按照订单子项的序号分组
     *
     * @param cateringOrderItemDOS             订单子项集合
     * @param cateringOrderItemAccessoryDOList 第一次转换后的CateringOrderItemAccessoryDO集合
     * @return
     */
    private static Map<String, List<CateringOrderItemAccessoryDO>> toGroupBySeq(List<CateringOrderItemDO> cateringOrderItemDOS,
                                                                                List<CateringOrderItemAccessoryDO> cateringOrderItemAccessoryDOList) {
        Map<String, List<CateringOrderItemAccessoryDO>> seqAccessoryMap = Maps.newHashMap();
        List<CateringOrderItemAccessoryDO> accessoryDOList = Lists.newLinkedList();
        for (CateringOrderItemDO cateringOrderItemDO : cateringOrderItemDOS) {
            for (CateringOrderItemAccessoryDO accessoryDO : cateringOrderItemAccessoryDOList) {
                if (accessoryDO.getSeqNo().contains(cateringOrderItemDO.getSeqNo().substring(0, 1))) {
                    accessoryDOList.add(accessoryDO);
                    seqAccessoryMap.put(cateringOrderItemDO.getSeqNo(), accessoryDOList);
                }
            }
        }
        return seqAccessoryMap;
    }

    /**
     * 根据accessoryId进行分组
     *
     * @param accessories 请求集合
     * @param tenantId    用户信息
     * @return
     */
    private static Map<Long, CateringOrderItemAccessoryDO> toGroupByAccessoryId(List<PlaceCateringOrderBizRequest.Item.Accessory> accessories, Long tenantId) {
        Map<Long, CateringOrderItemAccessoryDO> accessoryDOMap = accessories.stream()
                .collect(Collectors.toMap(PlaceCateringOrderBizRequest.Item.Accessory::getProductAccessoryId,
                        item -> toCateringOrderItemAccessoryDO(item, tenantId)));
        return accessoryDOMap;
    }

    /**
     * 将请求中的Accessory对象转换为CateringOrderItemAccessoryDO对象
     *
     * @param accessory 请求中的对象
     * @param tenantId  用户信息
     * @return
     */
    private static CateringOrderItemAccessoryDO toCateringOrderItemAccessoryDO(PlaceCateringOrderBizRequest.Item.Accessory accessory, Long tenantId) {
        CateringOrderItemAccessoryDO cateringOrderItemAccessoryDO = new CateringOrderItemAccessoryDO();
        cateringOrderItemAccessoryDO.setTenantId(tenantId);
        cateringOrderItemAccessoryDO.setSeqNo(accessory.getSeqNo());
        cateringOrderItemAccessoryDO.setStatus(CateringOrderItemAccessoryStatusEnum.PLACED);
        cateringOrderItemAccessoryDO.setPlaceQuantity(accessory.getQuantity());
        cateringOrderItemAccessoryDO.setProduceQuantity(new BigDecimal(0));
        cateringOrderItemAccessoryDO.setLatestQuantity(accessory.getQuantity());
        cateringOrderItemAccessoryDO.setProductAccessoryId(accessory.getProductAccessoryId());
        return cateringOrderItemAccessoryDO;
    }

    /**
     * 出餐：参数转换为CateringOrderItemAccessoryDO集合
     *
     * @param accessoryDOList 数据库中查询出来的加料集合
     * @param items           请求中的item集合
     * @return
     */
    public static List<CateringOrderItemAccessoryDO> toItemAccessoryDO(List<CateringOrderItemAccessoryDO> accessoryDOList,
                                                                       List<ProduceCateringOrderBizRequest.Item> items) {
        List<CateringOrderItemAccessoryDO> accessoryDOS = Lists.newLinkedList();
        Map<String, CateringOrderItemAccessoryDO> accessoryDOMap = accessoryDOList.stream()
                .collect(Collectors.toMap(CateringOrderItemAccessoryDO::getSeqNo, item -> item));
        for (ProduceCateringOrderBizRequest.Item item : items) {
            for (ProduceCateringOrderBizRequest.Item.Accessory accessory : item.getAccessories()) {
                if (accessoryDOMap.containsKey(accessory.getSeqNo())) {
                    CateringOrderItemAccessoryDO accessoryDO = accessoryDOMap.get(item.getSeqNo());
                    if (accessory.getQuantityOnProduce().add(accessoryDO.getProduceQuantity()).equals(accessoryDO.getPlaceQuantity())) {
                        accessoryDO.setStatus(CateringOrderItemAccessoryStatusEnum.PREPARED);
                    }
                    accessoryDO.setProduceQuantity(accessory.getQuantityOnProduce().add(accessoryDO.getProduceQuantity()));
                    accessoryDOS.add(accessoryDO);
                }
            }

        }
        return accessoryDOS;
    }

    /**
     * 制作：部分参数转换
     *
     * @param userContextBO   用户信息
     * @param accessoryDOList 数据库中查询出来的加料集合
     * @param items           请求中的item集合
     * @return
     */
    public static List<CateringOrderItemAccessoryDO> toItemAccessory(UserContextBO userContextBO, List<CateringOrderItemAccessoryDO> accessoryDOList, List<PrepareCateringOrderBizRequest.Item> items) {
        List<CateringOrderItemAccessoryDO> accessoryDOS = Lists.newLinkedList();
        for (CateringOrderItemAccessoryDO cateringOrderItemAccessoryDO : accessoryDOList) {
            cateringOrderItemAccessoryDO.setStatus(CateringOrderItemAccessoryStatusEnum.PREPARING);
            cateringOrderItemAccessoryDO.setTenantId(userContextBO.getTenantId());
            accessoryDOS.add(cateringOrderItemAccessoryDO);
        }
        return accessoryDOS;
    }
}
